using OrchardCore.Taxonomies.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace OrchardCore.ContentManagement;

public static class ContentManagerExtensions
{
    /// <summary>
    /// 获取具有指定 <paramref name="id"/> 的已发布内容项，并将其作为提供的 <typeparamref name="T"/> <see cref="ContentPart"/> 返回。
    /// </summary>
    public static async Task<T> GetAsync<T>(this IContentManager contentManager, string id)
        where T : ContentPart
        => (await contentManager.GetAsync(id))?.As<T>();

    /// <summary>
    /// 获取具有指定 <paramref name="id"/> 和版本的内容项，并将其作为提供的 <typeparamref name="T"/> <see cref="ContentPart"/> 返回。
    /// </summary>
    /// <param name="id">要检索的内容项的 ID。</param>
    /// <param name="versionOptions">要检索的内容项的版本数据。</param>
    public static async Task<T> GetAsync<T>(this IContentManager contentManager, string id, VersionOptions versionOptions)
        where T : ContentPart
        => (await contentManager.GetAsync(id, versionOptions))?.As<T>();

    /// <summary>
    /// 如果给定的 <paramref name="contentItem"/> 尚不存在，则使用新版本持久化它，如果它已存在，则在不创建新版本的情况下更新它。
    /// </summary>
    public static Task CreateOrUpdateAsync(this IContentManager contentManager, ContentItem contentItem) =>
        contentItem.Id == 0
            ? contentManager.CreateAsync(contentItem, VersionOptions.Published)
            : contentManager.UpdateAsync(contentItem);

    /// <summary>
    /// 如果提供的 <paramref name="contentItem"/> 为 <see langword="null"/>，则使用指定的 <paramref name="name"/> 作为内容类型创建新的内容项，否则加载提供的 <paramref name="contentItem"/>。
    /// </summary>
    /// <param name="contentItem">要加载的内容项。</param>
    /// <param name="name">新创建的内容项的类型。</param>
    /// <returns>新创建或加载的内容项。</returns>
    public static Task<ContentItem> NewOrLoadAsync(
        this IContentManager contentManager,
        ContentItem contentItem,
        string name) =>
        contentItem == null ? contentManager.NewAsync(name) : contentManager.LoadAsync(contentItem);

    /// <summary>
    /// 检索在 <paramref name="taxonomyAlias"/> 中提供别名的分类内容项的术语。
    /// </summary>
    /// <returns>包含分类内容项术语的只读列表。</returns>
    public static async Task<IReadOnlyList<ContentItem>> GetTaxonomyTermsAsync(
        this IContentManager contentManager,
        IContentHandleManager contentHandleManager,
        string taxonomyAlias)
    {
        var taxonomyContentItemId = await contentHandleManager.GetContentItemIdAsync($"alias:{taxonomyAlias}");
        var taxonomy = string.IsNullOrEmpty(taxonomyContentItemId)
            ? null
            : await contentManager.GetAsync(taxonomyContentItemId);

        return taxonomy?.As<TaxonomyPart>()?.Terms;
    }

    /// <summary>
    /// 检索属于由提供的 <paramref name="taxonomyId"/> 标识的分类内容项的术语的显示文本。
    /// </summary>
    /// <returns>
    /// 一个字典，其中键包含术语的 ID，值包含术语的显示文本。
    /// </returns>
    public static async Task<IDictionary<string, string>> GetTaxonomyTermsDisplayTextsAsync(
        this IContentManager contentManager,
        string taxonomyId) =>
        (await contentManager.GetAsync(taxonomyId))
        .As<TaxonomyPart>()
        .Terms
        .ToDictionary(term => term.ContentItemId, term => term.DisplayText);

    /// <summary>
    /// 返回由其 <paramref name="termId"/> 标识的特定术语在其 <paramref name="alias"/> 标识的分类中的 <see cref="ContentItem.DisplayText"/>。如果未找到任何内容，则返回 <see langword="null"/>。
    /// </summary>
    public static async Task<string> GetTaxonomyTermDisplayTextAsync(
        this IContentManager contentManager,
        IContentHandleManager contentHandleManager,
        string alias,
        string termId) =>
        (await contentManager.GetTaxonomyTermsAsync(contentHandleManager, alias))
        .FirstOrDefault(term => term.ContentItemId == termId)?
        .DisplayText;

    /// <summary>
    /// 返回由 <see cref="ContentItem.ContentItemId"/> 标识的给定类型的 <see cref="ContentItem"/>。如果未提供 <see cref="VersionOptions"/>，则获取已发布版本。
    /// </summary>
    /// <param name="contentType">所需 <see cref="ContentItem"/> 的内容类型。</param>
    /// <param name="contentItemId"><see cref="ContentItem"/> 的 ID。</param>
    /// <param name="versionOptions"><see cref="ContentItem"/> 的版本（例如，Published、Latest）。</param>
    /// <returns>获取的或新创建的 <see cref="ContentItem"/>。</returns>
    public static async Task<ContentItem> GetOfTypeAsync(
        this IContentManager contentManager,
        string contentItemId,
        string contentType,
        VersionOptions versionOptions = null)
    {
        var contentItem = await contentManager.GetAsync(contentItemId, versionOptions ?? VersionOptions.Published);

        return contentItem.ContentType == contentType ? contentItem : null;
    }

    /// <summary>
    /// 返回由 <see cref="ContentItem.ContentItemId"/> 标识的给定类型的 <see cref="ContentItem"/>。如果未提供 ID，则创建新的。
    /// </summary>
    /// <param name="contentType">所需 <see cref="ContentItem"/> 的内容类型。</param>
    /// <param name="contentItemId"><see cref="ContentItem"/> 的 ID。</param>
    /// <param name="versionOptions"><see cref="ContentItem"/> 的版本（例如，Published、Latest）。</param>
    /// <returns>获取的或新创建的 <see cref="ContentItem"/>。</returns>
    public static Task<ContentItem> GetOrCreateAsync(
        this IContentManager contentManager,
        string contentItemId,
        string contentType,
        VersionOptions versionOptions = null)
    {
        if (string.IsNullOrEmpty(contentType))
        {
            return contentManager.GetOfTypeAsync(contentItemId, contentType, versionOptions);
        }

        return string.IsNullOrEmpty(contentItemId)
            ? contentManager.NewAsync(contentType)
            : contentManager.GetOfTypeAsync(contentItemId, contentType, versionOptions);
    }
}
